//****************************************************************************
//                      TCON_AL_G01
//
//功能：
//
//版本:
//TCON_AL_G01_X01	yshao       2021/04/27
//					
//TCON_AL_G01_X02	yshao       2021/04/28
//					lvds in, mini lvds out
//TCON_AL_G01_X08	yshao       2021/05/08
//					显示OK
//TCON_AL_G01_X09	yshao       2021/05/08
//					调整位置
//TCON_AL_G01_X10	yshao       2021/05/08
//					添加调试信号
//TCON_AL_G02_X06	yshao       2021/05/18
//					调整oclk和clk2z时序，调整像素写入映射
//TCON_AL_G02_X07	yshao       2021/05/18
//					buf_r_sel改用out_flag = 0 清零，防止vs和de时序不同导致错误
//TCON_AL_G02_X09	yshao       2021/05/28
//					8bit->10bit，miniLVDS相位75，miniLVDS摆幅250mV
//TCON_AL_G02_X10	yshao       2021/05/28
//					输出逻辑使用clk2x和dsync
//TCON_AL_G02_X11	yshao       2021/06/03
//					调整输出位置
//TCON_AL_G02_X12	yshao       2021/06/03
//					在测试模式关闭色彩映射
//TCON_AL_G02_X17_1	yshao       2021/06/24
//					从TCON_AL_G02_X17增加调试信号
//TCON_AL_G02_X17_2	yshao       2021/06/24
//					启动时屏蔽不完整帧,GOA从STV开始输出
//TCON_AL_G02_X17_4	yshao       2021/06/24
//					优化时序约束
//TCON_AL_G02_X17_5	yshao       2021/06/24
//					屏蔽不完整正输入信号
//TCON_AL_G02_X18	yshao       2021/06/27
//					将LVDS相位改回22度
//TCON_AL_G02_X20	yzl         2021/07/07
//					minilvds区域约束，clk2x与clk4xsft可调范围为0-340度
//TCON_AL_G02_X21	yzl         2021/08/06
//					增加iic接口，支持回读版本号
//****************************************************************************
module TCON_AL_G60(
	//时钟
	// input   wire            osc_25m,   // frequency generator clock input
	
	//LVDS输入
	input	wire	[1:0]	CLKIN,
	input	wire	[7:0]	DATAIN,

	//MINI LVDS输出
	output	wire	[1:0]	CLKOUT,
	output	wire	[5:0]	DATAOUT,

	//output	wire	[5:0]	DATAOUT1,
	//SOC接口
	inout	    			F_SDA,
	input	wire			F_SCL,
	input	wire			G_WP,
	input	wire			SEL_LVDS,
	input	wire			BIST,
	
	//oc控制信号
	output	wire			POL,
	output	wire			CPV,
	output	wire			TP,
	output	wire			STV1,
	output	wire			STV2,
	output	wire			SHL,
	output	wire			PAIR,
	output	wire			OE1,
	output	wire			XON,
	output	wire			UD,
	output	wire			S1_L,

	//LS信号输出
	output	wire			STV_IC,
	output	wire			CLK1_IC,
	output	wire			CLK2_IC,
	output	wire			CLR_IC,
  
	//GAM信号

	//OC flash 预留
	output	wire			WP,
	output	wire			SCS,
	output	wire			SCK,
	output	wire			SDO,
	input	wire			SDI,

	//调试信号
	output	wire			S_SDA,
	output	wire			S_SCL
);
//程序版本信息
parameter	MAIN_FUNCTION    =  "F"      ;//"F"  
parameter	SUB_FUNCTION     =  "G"      ;//"G"  
parameter	MAIN_SOLUTION    =  8'd1     ;//"1"        
parameter	SUB_SOLUTION     =  8'd1     ;//"01"       
parameter	APPLICATION_TYPE =  "G"      ;//"G"  
parameter	MAIN_VERSION     =  8'd2     ;//"01"       
parameter	SUB_VERSION      =  8'd0     ;//"0"
parameter	MINI_VERSION     =  8'd21    ;//"06"  
parameter	YEARS            =  8'd21    ;//"06"  
parameter	MONTHS           =  8'd08    ;//"06"  
parameter	DAYS             =  8'd06    ;//"06"  
parameter	T4S              =  32'd297;
parameter	T3S              =  32'd222;


//模块参数设置
defparam	iic_comm_u.main_function    = MAIN_FUNCTION     ;
defparam	iic_comm_u.sub_function     = SUB_FUNCTION      ;
defparam	iic_comm_u.main_solution    = MAIN_SOLUTION     ;
defparam	iic_comm_u.sub_solution     = SUB_SOLUTION      ;
defparam	iic_comm_u.application_type = APPLICATION_TYPE  ;
defparam	iic_comm_u.main_version     = MAIN_VERSION      ;
defparam	iic_comm_u.sub_version      = SUB_VERSION       ;
defparam	iic_comm_u.mini_version     = MINI_VERSION      ;
defparam	iic_comm_u.years            = YEARS             ;
defparam	iic_comm_u.months           = MONTHS            ;
defparam	iic_comm_u.days             = DAYS              ;

//******************************************************************************
//                              参数定义
//******************************************************************************

//******************************************************************************
//                              信号定义
//******************************************************************************
//复位&时钟
        wire			cclk, clk_27M, sclk, clk1x,clk1x_t, clk2x, clk3p5x, clk3p5x90, clk4x,  clk4x_sft90;
        wire			extlock, rstn, resetb, TX_rst, out_rst;

//设置信号
(*keep*)wire			cfg_wen;
(*keep*)wire	[11:0]	cfg_waddr;
(*keep*)wire	[7:0]	cfg_wdata;

//LVDS接收
(*keep*)wire			vs0_a, hs0_a, de0_a, vs1_a, hs1_a, de1_a;
(*keep*)wire	[7:0]	r0_a, g0_a, b0_a, r1_a, g1_a, b1_a;

(*keep*)reg				vs0_p, hs0_p, vs1_p, hs1_p;
(*keep*)reg				vs0, hs0, de0,vs1, hs1, de1;
(*keep*)reg		[7:0]	r0,  g0,  b0, r1,  g1,  b1;

(*keep*)wire			vs_a, hs_a, de_a;
(*keep*)wire	[47:0]	data_a;
(*keep*)wire			vs_b, hs_b, de_b;
(*keep*)wire	[47:0]	data_b;
(*keep*)wire			oclk, deout;
(*keep*)wire	[47:0]	dout;

(*keep*)wire			err_flag1,err_flag0, test_mode;

//
(*keep*)wire			iSdaI;
(*keep*)wire			oSdaO;
(*keep*)wire			oSdaOE;
        reg     [ 3:0]	rst_init_cnt;
        wire         	rst_init_n;
        reg     [31:0]	rst_temp ;
        reg 			SYS_RST_N;
(*keep*)wire			mcu_clk, mcu_cs, mcu_dat_in, mcu_dat_out;
        reg				vs_aa, work_mode;
        reg		[ 5:0]	vs_rst_count;
		wire			lvds_ok;

//******************************************************************************
//                              sclk & 复位 & LED
//******************************************************************************
//基础时钟

EG_LOGIC_CCLK  #(
	.FREQ("30.0"))
cclk0	
(
	.cclk( cclk ),
	.en( 1'd1 ));

BUFG_inst BUFG_inst (
    .i(cclk),  // 1-bit input: Clock input
    .o(sclk) // 1-bit output: Clock output
);


//复位模块
rst_led rst_led
(
     .sck         (sclk),
//	 .sck         (CLKIN[0]),
    
    .rst         ( rstn ),
    .led         (	),
    
    .I_time_1ms_sync  (),
    .I_vsync     (1'b0), 
    .rst_lvds    ()
    );

always @(posedge  CLKIN[0] )begin
	if(rst_init_cnt <4'h8) begin
		rst_init_cnt <= rst_init_cnt + 1;
	end
	else begin
		rst_init_cnt <= rst_init_cnt ;    
	end
end 

assign rst_init_n = rst_init_cnt[3];
 
always@(posedge CLKIN[0] or negedge rst_init_n) begin
    if (rst_init_n == 1'b0) 
        rst_temp <= 'd0;
	else if(rst_temp < T4S)
		rst_temp <=rst_temp + 1'b1;
	else 
		rst_temp <=T4S;
end   

always @(posedge CLKIN[0] or negedge rst_init_n) begin
    if (rst_init_n == 1'b0) 
        SYS_RST_N <=1'b0; 
	else if(rst_temp>32'd5&&rst_temp < T3S)
		SYS_RST_N <=1'b0;
	else 
		SYS_RST_N <=1'b1;
end

PLL_IP2 PLL_IP2(
	.refclk		( CLKIN[0] ),
	// .reset		( 1'b0 ),
	.reset		( ~SYS_RST_N ),
		
	.clk0_out	( clk1x ),
	.clk1_out	( clk3p5x ),
	.extlock	( extlock	));

assign	resetb = rstn && extlock ;
//******************************************************************************
//                              IIC接口
//******************************************************************************
assign iSdaI = F_SDA;
assign F_SDA = ~oSdaOE ? oSdaO : 1'bz;

iic_comm
    iic_comm_u(
    //CLK & Reset
	.iSysClk             (sclk   ),// CLK
	.iSysRstN            (rstn   ),// active high

    .iSlvAddr            (7'h5A  ),// Slave Address
    .iSerSel             (1'b1   ),// Serial line select (0:Disable 1:Enable)
    .iSCL                (F_SCL  ),// IIC Serial Clock
    .iSdaI               (iSdaI  ),// IIC Serial Clock
    .oSdaO               (oSdaO  ),// IIC Serial Output
    .oSdaOE              (oSdaOE ) // IIC Serial Output enable (1:HiZ 0:Output)
);

//******************************************************************************
//                              配置接口
//******************************************************************************
assign	mcu_clk		= 0;
assign	mcu_cs		= 0;
assign	mcu_dat_in	= 0;
//assign	SEL_LVDS	= mcu_dat_out;

spi_comm u_spi_comm (
		//时钟和复位
	    .resetb			(resetb),
	    .sclk			(sclk),
	    
		//MCU接口
		.I_mcu_clk		(mcu_clk),
	    .I_mcu_cs		(mcu_cs),
	    .I_mcu_dat_in	(mcu_dat_in),
	    .O_mcu_dat_out	(mcu_dat_out),
	    
		//设置接口
	    .cfg_wen		(cfg_wen),
	    .cfg_waddr		(cfg_waddr),
	    .cfg_wdata		(cfg_wdata),
	    
		//调试信号
	    .tout			()
		);

//******************************************************************************
//                              LVDS接收
//******************************************************************************
LVDS_RX_VESA  LVDS_RX(
  .rstn			( resetb   ),
  .LVDS_IN_VESA	( 1'b1   ) ,
  .clk1x		( clk1x ),
  .clk3p5x		( clk3p5x ),
  
  .iLVDSCK		( CLKIN ),
  .iLVDSRX		( DATAIN ),
  
  .vs0			( vs0_a	 ),
  .hs0			( hs0_a	 ),
  .de0			( de0_a	 ),
  .r0			( r0_a	 ),
  .g0			( g0_a	 ),
  .b0			( b0_a	 ),
                  
  .vs1			( vs1_a	 ),
  .hs1			( hs1_a	 ),
  .de1			( de1_a	 ),
  .r1			( r1_a	 ),
  .g1			( g1_a	 ),
  .b1			( b1_a	 )
);

//信号延时
always @(posedge clk1x)	begin
	de0 <= de0_a;
	r0 <= r0_a;
	g0 <= g0_a;
	b0 <= b0_a;
	end 

//极性自适应
always @(posedge clk1x or negedge resetb)
	if (resetb == 0) begin
		vs0_p <= 0;
		hs0_p <= 0;
		end 
	else if ((de0_a == 1) && (de0 == 0))begin
		vs0_p <= vs0_a;
		hs0_p <= hs0_a;
		end

always @(posedge clk1x)	begin
	vs0 <= vs0_a + vs0_p;
	hs0 <= hs0_a + hs0_p;
	end 

always @(posedge clk1x)	begin
	de1 <= de0_a;
	r1 <= r1_a;
	g1 <= g1_a;
	b1 <= b1_a;
	end 

always @(posedge clk1x or negedge resetb)
	if (resetb == 0) begin
		vs1_p <= 0;
		hs1_p <= 0;
		end 
	else if ((de1_a == 1) && (de1 == 0))begin
		vs1_p <= vs1_a;
		hs1_p <= hs1_a;
		end

always @(posedge clk1x)	begin
	vs1 <= vs1_a + vs1_p;
	hs1 <= hs1_a + hs1_p;
	end 

//******************************************************************************
de_err_dect de_err_dect1(
		.pclk	(clk1x),
		
		.hsin	(hs1 ),
		.dein	(de1 ),
		
		.err_flag( err_flag1 ),
		
		.tout  () 
		);

de_err_dect de_err_dect0(
		.pclk	(clk1x),
		
		.hsin	(hs0 ),
		.dein	(de0 ),
		
		.err_flag( err_flag0 ),
		
		.tout  () 
		);

test_dect test_dect(
		.resetb		(resetb),
		.pclk		(clk1x),
		
		.vsin		(vs0 ),
		
		.test_mode	(test_mode),
		
		.tout  () 
		);

assign	vs_a = vs0;
assign	hs_a = hs0;
assign	de_a = de0;
assign	data_a = {b1, g1, r1, b0, g0, r0};

//******************************************************************************
//                              开机屏蔽
//******************************************************************************
//帧信号延时
always @(posedge clk1x)
	vs_aa <= vs_a;

//帧信号复位后计数
always @(posedge clk1x or negedge resetb)
	if (resetb == 0)
		vs_rst_count <= 0;
	else if ((vs_a == 0) && (vs_aa == 1)) begin
		if (work_mode == 0)
			vs_rst_count <= vs_rst_count + 1;
	end

//工作使能
always @(posedge clk1x)
	if (vs_rst_count > 1)
		work_mode <= 1;
	else
		work_mode <= 0;

assign	TX_rst	= resetb & out_rst;// & vs_resetb;

//******************************************************************************
//                              灰度变换
//******************************************************************************
RGB_maping RGB_maping(
		.resetb			(resetb),
		.sclk			(sclk),
			
		.test_mode		(test_mode),
		.work_mode		(work_mode),
		
		.cfg_wen		(cfg_wen),
		.cfg_waddr		(cfg_waddr),
		.cfg_wdata		(cfg_wdata),
		
		.pclk			(clk1x),
		.vsin			(vs_a),
		.hsin			(hs_a),
		.dein			(de_a),
		.din			(data_a),
		
		.vsout			(vs_b),
		.hsout			(hs_b),
		.deout			(de_b),
		.dout			(data_b)
		);

//******************************************************************************
//                              输入图像变频
//******************************************************************************
assign STV2 = deout;
t_repeat t_repeat(
        //时钟 & 复位
		.resetb			(resetb),
		.lvds_ok		(lvds_ok),
        //输入信号
		.ckin			({clk1x,clk1x}),
	    .vsin			({vs_b, vs_b}),
	    .hsin			({hs_b, hs_b}),
	    .dein			({de_b, de_b}),
	    .din			( data_b ),
		
        //最终输出时序
        .clk2x			(clk2x),
        .dsync			(dsync),
		.deout			(deout),
		.dout			(dout),

        //TCON辅助时序
		.POL			(POL),
		.CPV			(CPV),
		.TP				(TP),
		.STV1			(STV1),
		.STV2			(),
		.SHL			(SHL),
		.PAIR			(PAIR),
		.OE1			(OE1),
		.XON			(XON),
		.UD				(UD),
		.S1_L			(S1_L),

		//调试信号
		.tout			()
		);		
		
		
lvds_init_dect u_lvds_init_dect(
		.resetb			(resetb),
		.pclk			(clk1x),
		.vsin			(vs0),
		.lvds_ok		(lvds_ok),
		.tout			()
		);

//******************************************************************************
//                              mini_LVDS输出
//******************************************************************************
mini_LVDS_out u_mini_LVDS(
        //时钟 & 复位
		.resetb			(resetb),
		.sclk			(CLKIN[0]),		
//		.sclk			(sclk),
        
        //最终输出时序
        .clk2x			(clk2x),
        .dsync			(dsync),
		.deout			(deout),
		.dout			(dout),

		//mini LVDS output
		.CLKOUT			(CLKOUT),
		.DATAOUT		(DATAOUT),
		//.DATAOUT		(data_t),
		.out_rstb		(out_rst),
        
        .tout()
        );         
/*
mini_LVDS_out u_mini_LVDS1(
        //时钟 & 复位
		.resetb			(resetb),
		.sclk			(CLKIN[0]),		
//		.sclk			(sclk),
        
        //最终输出时序
        .clk2x			(),
        .dsync			(),
		.deout			(deout),
		.dout			(dout),

		//mini LVDS output
		.CLKOUT			(),
		.DATAOUT		(DATAOUT1),
		//.DATAOUT		(data_t),
		.out_rstb		(),
        
        .tout()
        ); 	        
*/	
//******************************************************************************
//                             输出接口
//******************************************************************************
assign	S_SDA  =  0;//deout;
// assign	S_SCL  =  0;//CLK1_IC;
assign	S_SCL  =  &data_a;//CLK1_IC;

//******************************************************************************
//                             调试信号
//******************************************************************************
//assign	F_SCL		= de0;
//assign	F_SDA		= STV_IC;

//assign	BIST		= CLR_IC;
//assign	SEL_LVDS	= CLK2_IC;
//assign	G_WP		= TP;

//assign	tout	= ^{vs0,hs0,de0,vs1,hs1,de1,r0,g0,b0,r1,g1,b1};

endmodule
